package com.vca.service.service.Impl;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageInfo;
import com.vca.common.constants.CategoryConstants;
import com.vca.common.constants.Constants;
import com.vca.common.constants.SysConfigConstants;
import com.vca.common.constants.SysGroupDataConstants;
import com.vca.common.exception.VcaException;
import com.vca.common.model.category.Category;
import com.vca.common.model.course.*;
import com.vca.common.model.exhibition.Exhibition;
import com.vca.common.model.system.SystemAttachment;
import com.vca.common.model.talk.Talk;
import com.vca.common.model.user.User;
import com.vca.common.model.user.UserCollection;
import com.vca.common.model.vca_product.VcaProduct;
import com.vca.common.request.*;
import com.vca.common.response.*;
import com.vca.common.utils.PageUtils;
import com.vca.common.vo.*;
import com.vca.service.dao.course.CourseDao;
import com.vca.service.service.*;
import com.vca.service.util.UmsUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 课程表 服务实现类
 * </p>
 *
 * @author chenBing
 * @since 2022-09-19
 */
@Service
@Slf4j
public class CourseServiceImpl extends ServiceImpl<CourseDao, Course> implements CourseService {

    @Resource
    private CourseDao dao;

    @Autowired
    private CourseSchedulingService courseSchedulingService;

    @Autowired
    private CategoryService categoryService;

    @Autowired
    private SystemGroupDataService systemGroupDataService;

    @Autowired
    private CourseDao courseDao;

    @Autowired
    private CourseInfoService courseInfoService;

    @Autowired
    private CourseAboutService courseAboutService;

    @Autowired
    private UmsUtils umsUtils;

    @Autowired
    private TalkService talkService;

    @Autowired
    private ExhibitionService exhibitionService;

    @Autowired
    private VcaProductService vcaProductService;

    @Autowired
    private SystemAttachmentService systemAttachmentService;

    @Autowired
    private SystemConfigService systemConfigService;

    @Autowired
    private TransactionTemplate transactionTemplate;

    @Autowired
    private UserService userService;

    @Autowired
    private UserCollectionService userCollectionService;

    @Autowired
    private CoursePackageService coursePackageService;

    @Autowired
    private CoursePackageRelationService coursePackageRelationService;

    @Autowired
    private VcaOrderService vcaOrderService;

    @Autowired
    private VcaLineUpService vcaLineUpService;


    @Override
    public String getAccessToken() {
        return umsUtils.getAccessToken();
    }

    /**
     * @Description:列表
     * @Author: chenBing
     * @Date: 2022/11/25
     */
    @Override
    public List<CourseListVo> getListNoPage(String language,CourseFilterRequest request) {
        List<CourseListVo> courseListVos = new ArrayList<>();
        LambdaQueryWrapper<Course> lqw = new LambdaQueryWrapper<>();
        lqw.eq(Course::getStatus, Constants.COURSE_STATUS_IS_SALE);
        if (StringUtils.isNotBlank(request.getDate())) {
            List<CourseScheduling> schedulingList = courseSchedulingService.list(new LambdaQueryWrapper<CourseScheduling>().eq(CourseScheduling::getSchedulingDate, request.getDate()).eq(CourseScheduling::getIsDel, false).eq(CourseScheduling::getIsCancel, false).eq(CourseScheduling::getStatus, true));
            List<CourseScheduling> schedulings = new ArrayList<>();
            schedulingList.forEach(scheduling -> {
                if (com.vca.common.utils.DateUtil.getSchedulingStatus(scheduling.getSchedulingDate(), scheduling.getSchedulingStartTime(), scheduling.getSchedulingEndTime()) != 0) {
                    schedulings.add(scheduling);
                }
            });
            schedulingList.retainAll(schedulings);
            List<Long> courseIds = new ArrayList<>();
            if (schedulingList.size() > 0) {
                schedulingList.forEach(s -> {
                    courseIds.add(s.getCourseId());
                });
                if (courseIds.size() > 0) {
                    lqw.in(Course::getId, courseIds);
                } else {
                    return bindCoursePackage(language,request, courseListVos);
                }
            } else {
                return bindCoursePackage(language,request, courseListVos);
            }
        }
        // TODO: 2022/9/20 判断课程日期是否为空
        if (StringUtils.isNotBlank(request.getCourseInterval())) {
            dateLimitUtilVo dateLimit = com.vca.common.utils.DateUtil.getDateLimit(request.getCourseInterval());
            // TODO: 2022/9/20 开始日期
            Date startDateTime = com.vca.common.utils.DateUtil.strToDate(dateLimit.getStartTime(), Constants.DATE_FORMAT_DATE);
            // TODO: 2022/9/20 结束日期
            Date endDateTime = com.vca.common.utils.DateUtil.strToDate(dateLimit.getEndTime(), Constants.DATE_FORMAT_DATE);
            List<CourseScheduling> schedulingList = courseSchedulingService.list(new LambdaQueryWrapper<CourseScheduling>().ge(CourseScheduling::getSchedulingDate, DateUtil.format(startDateTime, Constants.DATE_FORMAT_DATE)).le(CourseScheduling::getSchedulingDate, DateUtil.format(endDateTime, Constants.DATE_FORMAT_DATE)).eq(CourseScheduling::getIsDel, false).eq(CourseScheduling::getIsCancel, false));
            List<CourseScheduling> schedulings = new ArrayList<>();
            schedulingList.forEach(scheduling -> {
                if (com.vca.common.utils.DateUtil.getSchedulingStatus(scheduling.getSchedulingDate(), scheduling.getSchedulingStartTime(), scheduling.getSchedulingEndTime()) != 0) {
                    schedulings.add(scheduling);
                }
            });
            schedulingList.retainAll(schedulings);
            List<Long> courseIds = new ArrayList<>();
            if (schedulingList.size() > 0) {
                schedulingList.forEach(s -> {
                    courseIds.add(s.getCourseId());
                });
                if (courseIds.size() > 0) {
                    lqw.in(Course::getId, courseIds);
                } else {
                    return bindCoursePackage(language,request, courseListVos);
                }
            } else {
                return bindCoursePackage(language,request, courseListVos);
            }
        }
        // TODO: 2022/9/22 根据课程类型ids查询course
        if (StringUtils.isNotBlank(request.getCourseTypeIds())) {
            List<String> stringList = Arrays.asList(StringUtils.split(request.getCourseTypeIds(), ","));
            lqw.in(Course::getCourseTypeId, stringList);
        }
        // TODO: 2022/9/22 根据语言ids查询课程是否又满足course_language_ids的数据
        if (StringUtils.isNotBlank(request.getCourseLanguageIds())) {
            List<String> stringList = Arrays.asList(StringUtils.split(request.getCourseLanguageIds(), ","));
            List<Integer> languageIds = new ArrayList<>();
            stringList.forEach(s -> {
                languageIds.add(Integer.valueOf(s));
            });
            // TODO: 2022/9/23 查询课程语言关系数据
            List<CourseScheduling> list = courseSchedulingService.list(new LambdaQueryWrapper<CourseScheduling>().in(CourseScheduling::getCourseLanguageId, languageIds).eq(CourseScheduling::getIsDel, false).eq(CourseScheduling::getIsCancel, false).eq(CourseScheduling::getStatus, true));
            List<CourseScheduling> schedulings = new ArrayList<>();
            if (list.size() <= 0) {
                return bindCoursePackage(language,request, courseListVos);
            }
            list.forEach(scheduling -> {
                if (com.vca.common.utils.DateUtil.getSchedulingStatus(scheduling.getSchedulingDate(), scheduling.getSchedulingStartTime(), scheduling.getSchedulingEndTime()) != 0) {
                    schedulings.add(scheduling);
                }
            });
            list.retainAll(schedulings);
            List<Long> courseIds = new ArrayList<>();
            if (list.size() > 0) {
                list.forEach(c -> {
                    courseIds.add(c.getCourseId());
                });
                if (courseIds.size() > 0) {
                    lqw.in(Course::getId, courseIds);
                } else {
                    return bindCoursePackage(language,request, courseListVos);
                }
            } else {
                return bindCoursePackage(language,request, courseListVos);
            }
        }
        // TODO: 2022/9/22 查询课程价格
        if (StringUtils.isNotBlank(request.getCoursePriceIds())) {
            List<String> pricesIds = Arrays.asList(StringUtils.split(request.getCoursePriceIds(), ","));
            lqw.in(Course::getCoursePriceId, pricesIds);
        }
        // TODO: 2022/9/22 查询课程时长id查询课程时长
        if (StringUtils.isNotBlank(request.getCourseDurationIds())) {
            List<String> stringList = Arrays.asList(StringUtils.split(request.getCourseDurationIds(), ","));
            List<Integer> courseDurationIds = new ArrayList<>();
            stringList.forEach(s -> {
                courseDurationIds.add(Integer.valueOf(s));
            });
            lqw.in(Course::getCourseDurationId, courseDurationIds);
        }
        lqw.eq(Course::getIsRecycle, 0).eq(Course::getIsDeleted, 0);
        if (request.getIsSelect()) {
            lqw.eq(Course::getCourseTypeId, 840);
        } else {
            lqw.ne(Course::getCourseTypeId, 840);
        }
        List<Course> courseList = dao.selectList(lqw);
        if (courseList.size() <= 0) {
            return bindCoursePackage(language,request, courseListVos);
        }
        for (Course course : courseList) {
            CourseListVo courseListVo = new CourseListVo();
            BeanUtils.copyProperties(course, courseListVo);

            if("en".equals(language)){
                System.out.println("en------------------"+categoryService.getById(course.getCourseTypeId()).getNameEn());
                courseListVo.setTypeName(categoryService.getById(course.getCourseTypeId()).getNameEn());
                courseListVo.setName(courseListVo.getNameEn());
            }else{
                System.out.println("cn------------------"+categoryService.getById(course.getCourseTypeId()).getName());
                courseListVo.setTypeName(categoryService.getById(course.getCourseTypeId()).getName());
            }

            courseListVo.setTypeLabelColor(categoryService.getById(course.getCourseTypeId()).getLabelColor());
            courseListVo.setType(0);
            LambdaQueryWrapper<CourseScheduling> schedulerWrapper = new LambdaQueryWrapper<>();
            schedulerWrapper.eq(CourseScheduling::getStatus, true);
            schedulerWrapper.eq(CourseScheduling::getIsDel, false).eq(CourseScheduling::getIsCancel, false);
            schedulerWrapper.eq(CourseScheduling::getCourseId, course.getId());
            int day = Integer.parseInt(systemConfigService.getValueByKey(Constants.COURSE_SHOW_DAY));
            String dateToTenDayDate = DateUtil.format(DateUtil.offset(new Date(), DateField.DAY_OF_YEAR, day), "yyyy-MM-dd");
            schedulerWrapper.between(CourseScheduling::getSchedulingDate, DateUtil.format(new Date(), "yyyy-MM-dd"), dateToTenDayDate);
            List<CourseScheduling> schedulings = courseSchedulingService.list(schedulerWrapper);
            List<CourseScheduling> schedulingList = new ArrayList<>();
            schedulings.forEach(scheduling -> {
                if (com.vca.common.utils.DateUtil.getSchedulingStatus(scheduling.getSchedulingDate(), scheduling.getSchedulingStartTime(), scheduling.getSchedulingEndTime()) != 0) {
                    schedulingList.add(scheduling);
                }
            });
            schedulings.retainAll(schedulingList);
            if (schedulings.size() <= 0) {
                continue;
            }
            DateTime date = DateUtil.date();
            SchedulingVo schedulingV = new SchedulingVo();
            schedulingV.setScheduled(0L);
            schedulingV.setScheduledDateTime(date);
            List<SchedulingVo> schedulingVos = new ArrayList<>();
            for (CourseScheduling scheduling : schedulings) {
                SchedulingVo schedulingVo = new SchedulingVo();
                // TODO: 2022/11/25 yyyy-MM-dd HH:mm:ss
                String schedulingDate = scheduling.getSchedulingDate() + " " + scheduling.getSchedulingStartTime();
                DateTime dateTime = DateUtil.parse(schedulingDate, "yyyy-MM-dd HH:mm");
                schedulingVo.setScheduledDateTime(dateTime);
                schedulingVo.setScheduled(scheduling.getId());
                schedulingVos.add(schedulingVo);
            }
            schedulingVos.add(schedulingV);
            schedulingVos = schedulingVos.stream().sorted(Comparator.comparing(SchedulingVo::getScheduledDateTime)).collect(Collectors.toList());
            Long scheduledId = 0L;
            for (int i = 0; i < schedulingVos.size(); i++) {
                if (schedulingVos.get(i).getScheduled() == 0 && i + 1 < schedulingVos.size()) {
                    scheduledId = schedulingVos.get(i + 1).getScheduled();
                }
            }
            if (scheduledId == 0) {
                continue;
            }
            CourseScheduling courseScheduling = courseSchedulingService.getById(scheduledId);
            courseListVo.setPrice(getPrice(courseScheduling.getPriceId()));
            courseListVo.setSchedulingId(scheduledId);
            courseListVo.setSchedulingDate(courseScheduling.getSchedulingDate());
            courseListVo.setSchedulingStartTime(courseScheduling.getSchedulingStartTime());
            courseListVo.setSchedulingEndTime(courseScheduling.getSchedulingEndTime());
            courseListVo.setSchedulingSeatCount(courseScheduling.getExternalLimit());
            courseListVo.setSort(course.getSort());

            courseListVos.add(courseListVo);
        }

        System.out.println(courseListVos+"==========");
        courseListVos = bindCoursePackage(language,request, courseListVos);
        System.out.println(courseListVos+"@@@@@@@@@@");
        return courseListVos;
    }

    @Override
    public List<Course> getCourseAndDelete(List<Long> ids) {
        return dao.getCourses(ids);
    }

    @Override
    public List<Integer> getCalendar(Integer month, Integer year) {
        List<Course> courses = list(new LambdaQueryWrapper<Course>().eq(Course::getIsDeleted, 0).eq(Course::getStatus, 1).eq(Course::getIsRecycle, 0));
        if (courses.size() <= 0) {
            return null;
        }
        List<Long> courseIds = courses.stream().map(Course::getId).collect(Collectors.toList());
        LambdaQueryWrapper<CourseScheduling> lqw = new LambdaQueryWrapper<>();
        lqw.select(CourseScheduling::getId, CourseScheduling::getCourseId, CourseScheduling::getSchedulingDate);
        lqw.eq(CourseScheduling::getIsDel, 0).eq(CourseScheduling::getIsCancel, 0).eq(CourseScheduling::getStatus, 1);
        lqw.ge(CourseScheduling::getSchedulingDate, com.vca.common.utils.DateUtil.getMonthStartDay(month, year));
        lqw.le(CourseScheduling::getSchedulingDate, com.vca.common.utils.DateUtil.getMonthEndDay(month, year));
        lqw.in(CourseScheduling::getCourseId, courseIds);
        lqw.groupBy(CourseScheduling::getSchedulingDate).orderByAsc(CourseScheduling::getSchedulingDate);
        List<CourseScheduling> schedulingList = courseSchedulingService.list(lqw);
        List<Integer> dates = new ArrayList<>();
        for (CourseScheduling courseScheduling : schedulingList) {
            Date date = com.vca.common.utils.DateUtil.strToDate(courseScheduling.getSchedulingDate(), Constants.DATE_FORMAT_DATE);
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(date);
            int day = calendar.get(Calendar.DATE);
            dates.add(day);
        }
        return dates;
    }

    @Override
    public List<CourseVo> listNoScheduling(String language,CourseFilterRequest request) {

        String[] ids = request.getCourseIds().split(",");

        QueryWrapper<Course> queryWrapper = new QueryWrapper<>();
        queryWrapper.notIn("id", ids);
        queryWrapper.eq("is_deleted","0");
        queryWrapper.eq("status","1");

        if(StringUtils.isNotBlank(request.getDate())||StringUtils.isNotBlank(request.getCourseInterval())){
            return new ArrayList<CourseVo>();
        }


        if(StringUtils.isNotBlank(request.getCourseTypeIds())){
            List<String> courseTypeIds = Arrays.asList(request.getCourseTypeIds().split(","));
            queryWrapper.in("course_type_id",courseTypeIds);
        }
        if(StringUtils.isNotBlank(request.getCoursePriceIds())){
            List<String> coursePriceIds = Arrays.asList(request.getCoursePriceIds().split(","));
            queryWrapper.in("course_price_id",coursePriceIds);
        }
        if(StringUtils.isNotBlank(request.getCourseDurationIds())){
            List<String> courseDurationIds = Arrays.asList(request.getCourseDurationIds().split(","));
            queryWrapper.in("course_duration_id",courseDurationIds);
        }

        List<Course> courses = courseDao.selectList(queryWrapper);

        List<CourseVo> courseVoList = new ArrayList<>();
        courses.forEach(course -> {
            CourseVo courseVo = new CourseVo();
            courseVo.setId(course.getId());
            if("en".equals(language)){
                courseVo.setName(course.getNameEn());
            }else{
                courseVo.setName(course.getName());
            }
            courseVo.setCover(course.getCover());
            HashMap<String, Object> priceMap = systemGroupDataService.getMapByGid(SysGroupDataConstants.GROUP_DATA_ID_CLIENT_COURSE_PRICE, course.getCoursePriceId());
            String coursePrice = String.valueOf(priceMap.get("coursePrice"));
            BigDecimal price = new BigDecimal(coursePrice);
            courseVo.setPrice(price);

            courseVo.setTypeLabelColor(categoryService.getById(course.getCourseTypeId()).getLabelColor());

            if("en".equals(language)){
                courseVo.setTypeName(categoryService.getById(course.getCourseTypeId()).getNameEn());
            }else{
                courseVo.setTypeName(categoryService.getById(course.getCourseTypeId()).getName());
            }
            courseVoList.add(courseVo);
        });
        return courseVoList;
    }

    public List<CourseListVo> bindCoursePackage(String language,CourseFilterRequest request, List<CourseListVo> courseListVos) {
        List<CourseListVo> coursePackages = getCoursePackageList(language,request);
        if (coursePackages.size() > 0) {
            for (CourseListVo courseListVo : coursePackages) {
                //if("en".equals(language)){
                //    System.out.println(courseListVo.getNameEn()+"####"+courseListVo.getTypeNameEn());
                //    courseListVo.setName(courseListVo.getNameEn());
                //    courseListVo.setTypeName(courseListVo.getTypeNameEn());
                //}
                courseListVos.add(courseListVo);
            }
            System.out.println(courseListVos+"))))))))))))))");
        }
        //给list集合排序
        if (courseListVos.size() > 0) {
            // TODO: 2022/9/26 排序规则：先按照课程在前，套课在后排序，再按照sort降序,再根据上课日期升序，再根据上课开始时间升序，再根据剩余席位降序
//            courseListVos = courseListVos.stream().sorted(Comparator.comparing(CourseListVo::getType).thenComparing(Comparator.comparing(CourseListVo::getSort).reversed()).thenComparing(Comparator.comparing(CourseListVo::getSchedulingDate)).thenComparing(Comparator.comparing(CourseListVo::getSchedulingStartTime)).thenComparing(Comparator.comparing(CourseListVo::getSchedulingSeatCount).reversed())).collect(Collectors.toList());
            courseListVos = courseListVos.stream().sorted(Comparator.comparing(CourseListVo::getType).thenComparing(Comparator.comparing(CourseListVo::getSort).reversed())).collect(Collectors.toList());
        }
        return courseListVos;
    }

    public List<CourseListVo> getCoursePackageList(String language,CourseFilterRequest request) {
        List<CourseListVo> courseListVos = new ArrayList<>();
        LambdaQueryWrapper<CoursePackage> lqw = new LambdaQueryWrapper<>();
        List<String> stringList = new ArrayList<>();
        if (StringUtils.isNotBlank(request.getDate())) {
            List<CourseScheduling> schedulingList = courseSchedulingService.list(new LambdaQueryWrapper<CourseScheduling>().eq(CourseScheduling::getSchedulingDate, request.getDate()).eq(CourseScheduling::getStatus, true).eq(CourseScheduling::getIsDel, false).eq(CourseScheduling::getIsCancel, false));
            List<CourseScheduling> schedulings = new ArrayList<>();
            schedulingList.forEach(scheduling -> {
                if (com.vca.common.utils.DateUtil.getSchedulingStatus(scheduling.getSchedulingDate(), scheduling.getSchedulingStartTime(), scheduling.getSchedulingEndTime()) != 0) {
                    schedulings.add(scheduling);
                }
            });
            schedulingList.retainAll(schedulings);
            List<Long> courseIds = new ArrayList<>();
            if (schedulingList.size() > 0) {
                schedulingList.forEach(s -> {
                    courseIds.add(s.getCourseId());
                });
                List<CoursePackageRelation> relationList = coursePackageRelationService.list(new LambdaQueryWrapper<CoursePackageRelation>().in(CoursePackageRelation::getCourseId, courseIds));
                List<Long> relationCourseIds = new ArrayList<>();
                for (CoursePackageRelation coursePackageRelation : relationList) {
                    relationCourseIds.add(coursePackageRelation.getCoursePackageId());
                }
                if (relationCourseIds.size() > 0) {
                    lqw.in(CoursePackage::getId, relationCourseIds);
                } else {
                    return courseListVos;
                }
            } else {
                return courseListVos;
            }
        }
        if (StringUtils.isNotBlank(request.getCourseInterval())) {
            dateLimitUtilVo dateLimit = com.vca.common.utils.DateUtil.getDateLimit(request.getCourseInterval());
            // TODO: 2022/9/20 开始日期
            Date startDateTime = com.vca.common.utils.DateUtil.strToDate(dateLimit.getStartTime(), Constants.DATE_FORMAT_DATE);
            // TODO: 2022/9/20 结束日期
            Date endDateTime = com.vca.common.utils.DateUtil.strToDate(dateLimit.getEndTime(), Constants.DATE_FORMAT_DATE);
            List<CourseScheduling> schedulingList = courseSchedulingService.list(new LambdaQueryWrapper<CourseScheduling>().ge(CourseScheduling::getSchedulingDate, DateUtil.format(startDateTime, Constants.DATE_FORMAT_DATE)).le(CourseScheduling::getSchedulingDate, DateUtil.format(endDateTime, Constants.DATE_FORMAT_DATE)).eq(CourseScheduling::getIsDel, false).eq(CourseScheduling::getIsCancel, false));
            List<CourseScheduling> schedulings = new ArrayList<>();
            schedulingList.forEach(scheduling -> {
                if (com.vca.common.utils.DateUtil.getSchedulingStatus(scheduling.getSchedulingDate(), scheduling.getSchedulingStartTime(), scheduling.getSchedulingEndTime()) != 0) {
                    schedulings.add(scheduling);
                }
            });
            schedulingList.retainAll(schedulings);
            List<Long> courseIds = new ArrayList<>();
            if (schedulingList.size() > 0) {
                schedulingList.forEach(s -> {
                    courseIds.add(s.getCourseId());
                });
                List<CoursePackageRelation> relationList = coursePackageRelationService.list(new LambdaQueryWrapper<CoursePackageRelation>().in(CoursePackageRelation::getCourseId, courseIds));
                List<Long> relationCourseIds = new ArrayList<>();
                for (CoursePackageRelation coursePackageRelation : relationList) {
                    relationCourseIds.add(coursePackageRelation.getCoursePackageId());
                }
                if (relationCourseIds.size() > 0) {
                    lqw.in(CoursePackage::getId, relationCourseIds);
                } else {
                    return courseListVos;
                }
            } else {
                return courseListVos;
            }
        }
        if (StringUtils.isNotBlank(request.getCourseTypeIds())) {
            stringList = Arrays.asList(request.getCourseTypeIds().split(","));
            List<Integer> typeIds = new ArrayList<>();
            stringList.forEach(s -> {
                typeIds.add(Integer.valueOf(s));
            });
            lqw.in(CoursePackage::getCourseTypeId, typeIds);
        }
        if (StringUtils.isNotBlank(request.getCoursePriceIds())) {
            stringList = Arrays.asList(request.getCoursePriceIds().split(","));
            List<Integer> priceIds = new ArrayList<>();
            stringList.forEach(s -> {
                priceIds.add(Integer.valueOf(s));
            });
            lqw.in(CoursePackage::getCoursePackagePriceId, priceIds);
        }
        if (StringUtils.isNotBlank(request.getCourseLanguageIds())) {
            // TODO: 2022/11/21 课程语言是否是普通话 根据语言参数Ids查询对应的课程，根据课程与套课关系表查询套课
            stringList = Arrays.asList(request.getCourseLanguageIds().split(","));
            List<Integer> languageIds = new ArrayList<>();
            stringList.forEach(s -> {
                languageIds.add(Integer.valueOf(s));
            });
            List<CourseScheduling> courseSchedulingList = courseSchedulingService.list(new LambdaQueryWrapper<CourseScheduling>().in(CourseScheduling::getCourseLanguageId, languageIds).eq(CourseScheduling::getIsDel, false).eq(CourseScheduling::getIsCancel, false));
            List<CourseScheduling> schedulings = new ArrayList<>();
            courseSchedulingList.forEach(scheduling -> {
                if (com.vca.common.utils.DateUtil.getSchedulingStatus(scheduling.getSchedulingDate(), scheduling.getSchedulingStartTime(), scheduling.getSchedulingEndTime()) != 0) {
                    schedulings.add(scheduling);
                }
            });
            courseSchedulingList.retainAll(schedulings);
            List<Long> courseIds = new ArrayList<>();

            if (courseSchedulingList.size() > 0) {
                courseSchedulingList.forEach(courseScheduling -> {
                    courseIds.add(courseScheduling.getCourseId());
                });
                List<CoursePackageRelation> coursePackageRelationList = coursePackageRelationService.list(new LambdaQueryWrapper<CoursePackageRelation>().in(CoursePackageRelation::getCourseId, courseIds));
                if (coursePackageRelationList.size() > 0) {
                    List<Long> coursePackageIds = new ArrayList<>();
                    coursePackageRelationList.forEach(coursePackageRelation -> {
                        if (!coursePackageIds.contains(coursePackageRelation.getCoursePackageId())) {
                            coursePackageIds.add(coursePackageRelation.getCoursePackageId());
                        }
                    });
                    if (coursePackageIds.size() > 0) {
                        lqw.in(CoursePackage::getId, coursePackageIds);
                    } else {
                        return courseListVos;
                    }
                } else {
                    return courseListVos;
                }
            } else {
                return courseListVos;
            }
        }
        if (StringUtils.isNotBlank(request.getCourseDurationIds())) {
            stringList = Arrays.asList(StringUtils.split(request.getCourseDurationIds(), ","));
            List<BigDecimal> courseDurations = new ArrayList<>();
            stringList.forEach(s -> {
                HashMap<String, Object> courseDurationMap = systemGroupDataService.getMapByGid(SysGroupDataConstants.GROUP_DATA_ID_CLIENT_COURSE_DURATION, Integer.valueOf(s));
                BigDecimal courseDuration = new BigDecimal(String.valueOf(courseDurationMap.get("courseDuration")));
                courseDurations.add(courseDuration);
            });
            lqw.in(CoursePackage::getDurationTotal, courseDurations);
        }
        lqw.eq(CoursePackage::getStatus, true).eq(CoursePackage::getIsRecycle, false).eq(CoursePackage::getIsDeleted, false);
        if (request.getIsSelect()) {
            lqw.eq(CoursePackage::getCourseTypeId, 840);
        } else {
            lqw.ne(CoursePackage::getCourseTypeId, 840);
        }
        List<CoursePackage> coursePackageList = coursePackageService.list(lqw);
        if (coursePackageList.size() <= 0) {
            return courseListVos;
        }
        System.out.println(coursePackageList+"222222222");
        for (CoursePackage coursePackage : coursePackageList) {
            CourseListVo courseListVo = new CourseListVo();
            BeanUtils.copyProperties(coursePackage, courseListVo);
            if("en".equals(language)){
                courseListVo.setTypeName(categoryService.getById(coursePackage.getCourseTypeId()).getNameEn());
                courseListVo.setName(courseListVo.getNameEn());
            }else{
                courseListVo.setTypeName(categoryService.getById(coursePackage.getCourseTypeId()).getName());
            }
            courseListVo.setTypeLabelColor(categoryService.getById(coursePackage.getCourseTypeId()).getLabelColor());
            courseListVo.setType(1);
            courseListVo.setCover(coursePackage.getCoverImage());
            courseListVo.setPrice(getPrice(coursePackage.getCoursePackagePriceId()));
            courseListVo.setSort(coursePackage.getSort());
            List<CoursePackageRelation> coursePackageRelationList = coursePackageRelationService.list(new LambdaQueryWrapper<CoursePackageRelation>().in(CoursePackageRelation::getCoursePackageId, coursePackage.getId()));
            List<Long> courseIds = coursePackageRelationList.stream().map(CoursePackageRelation::getCourseId).collect(Collectors.toList());
            if (courseIds.size() > 0) {
                int count = count(new LambdaQueryWrapper<Course>().in(Course::getId, courseIds).last("and (status = 0 or is_deleted = 1)"));
                if (count > 0) {
                    continue;
                }
            }
            System.out.println(courseListVo+"1111111111");
            List<CourseScheduling> courseSchedulings = new ArrayList<>();
            for (CoursePackageRelation coursePackageRelation : coursePackageRelationList) {
                LambdaQueryWrapper<CourseScheduling> schedulerWrapper = new LambdaQueryWrapper<>();
                schedulerWrapper.eq(CourseScheduling::getStatus, true);
                schedulerWrapper.eq(CourseScheduling::getIsDel, false).eq(CourseScheduling::getIsCancel, false);
                schedulerWrapper.eq(CourseScheduling::getCourseId, coursePackageRelation.getCourseId());
                List<CourseScheduling> schedulings = courseSchedulingService.list(schedulerWrapper);
                List<CourseScheduling> schedulingList = new ArrayList<>();
                schedulings.forEach(scheduling -> {
//                    if (com.vca.common.utils.DateUtil.getSchedulingStatus(scheduling.getSchedulingDate(), scheduling.getSchedulingStartTime(), scheduling.getSchedulingEndTime()) != 0) {
                        schedulingList.add(scheduling);
//                    }
                });
                schedulings.retainAll(schedulingList);
                if (schedulings.size() <= 0) {
                    continue;
                }
                schedulings.forEach(scheduling -> {
                    courseSchedulings.add(scheduling);
                });
            }
            DateTime date = DateUtil.date();
            SchedulingVo schedulingV = new SchedulingVo();
            schedulingV.setScheduled(0L);
            schedulingV.setScheduledDateTime(date);
            List<SchedulingVo> schedulingVos = new ArrayList<>();
            System.out.println(courseSchedulings+"!!!!!!!!!!");
            for (CourseScheduling scheduling : courseSchedulings) {
                SchedulingVo schedulingVo = new SchedulingVo();
                // TODO: 2022/11/25 yyyy-MM-dd HH:mm:ss
                String schedulingDate = scheduling.getSchedulingDate() + " " + scheduling.getSchedulingStartTime();
                DateTime dateTime = DateUtil.parse(schedulingDate, "yyyy-MM-dd HH:mm");
                schedulingVo.setScheduledDateTime(dateTime);
                schedulingVo.setScheduled(scheduling.getId());
                schedulingVos.add(schedulingVo);
            }
            schedulingVos.add(schedulingV);
            schedulingVos = schedulingVos.stream().sorted(Comparator.comparing(SchedulingVo::getScheduledDateTime)).collect(Collectors.toList());
            Long scheduledId = 0L;
            for (int i = 0; i < schedulingVos.size(); i++) {
                if (schedulingVos.get(i).getScheduled() == 0 && i + 1 < schedulingVos.size()) {
                    scheduledId = schedulingVos.get(i + 1).getScheduled();
                }
            }
            if (scheduledId == 0) {

                courseListVos.add(courseListVo);
                continue;
            }
            CourseScheduling courseScheduling = courseSchedulingService.getById(scheduledId);
            courseListVo.setSchedulingDate(courseScheduling.getSchedulingDate());
            courseListVo.setSchedulingStartTime(courseScheduling.getSchedulingStartTime());
            courseListVo.setSchedulingEndTime(courseScheduling.getSchedulingEndTime());
            courseListVo.setSchedulingSeatCount(courseScheduling.getExternalLimit());
            courseListVos.add(courseListVo);
        }
        return courseListVos;
    }

    /**
     * @Description:获取价格
     * @Author: chenBing
     * @Date: 2022/11/24
     */
    @Override
    public BigDecimal getPrice(Integer priceId) {
        HashMap<String, Object> priceMap = systemGroupDataService.getMapByGid(SysGroupDataConstants.GROUP_DATA_ID_CLIENT_COURSE_PRICE, priceId);
        if (priceMap == null) {
            return BigDecimal.valueOf(priceId);
        }
        String coursePrice = String.valueOf(priceMap.get("coursePrice"));
        BigDecimal price = new BigDecimal(coursePrice);
        return price;
    }

    @Override
    public List<CourseVo> getListCalendar(String language,CourseFilterRequest request) {
        List<CourseVo> courseVoList = new ArrayList<>();
        List<CourseListVo> courseVos = getListNoPage(language,request);
        courseVos.forEach(courseListVo -> {
            CourseVo courseVo = new CourseVo();
            BeanUtils.copyProperties(courseListVo, courseVo);
            courseVo.setSeatCount(courseListVo.getSchedulingSeatCount());
            courseVo.setPrice(new BigDecimal(String.valueOf(courseListVo.getPrice())));
            courseVoList.add(courseVo);
        });
        return courseVoList;
    }

    /**
     * @param coursePackageId 套课ID
     * @Description:套课详情
     * @Author: chenBing
     * @Date: 2022/11/21
     */
    @Override
    public CourseVo packageInfo(String language,Long coursePackageId) {
        CoursePackage coursePackage = coursePackageService.getById(coursePackageId);
        if (coursePackage != null) {
            return getCoursePackageInfo(language,coursePackage, null);
        }
        return null;
    }

    private static Long coursePackageId = 0L;

    /**
     * @Description:获取套课详情
     * @Author: chenBing
     * @Date: 2022/11/21
     */
    private CourseVo getCoursePackageInfo(String language,CoursePackage coursePackage, CourseFilterRequest request) {
        User user = userService.getInfo();
        CourseVo courseVo = new CourseVo();
        BeanUtils.copyProperties(coursePackage, courseVo);
        if (StringUtils.isNotBlank(coursePackage.getMainPictureVideo())) {
            SystemAttachment systemAttachment = systemAttachmentService.getOne(new LambdaQueryWrapper<SystemAttachment>().eq(SystemAttachment::getSattDir, coursePackage.getMainPictureVideo()));
            courseVo.setMainPictureVideoWidth(systemAttachment.getAttWidth());
            courseVo.setMainPictureVideoHeight(systemAttachment.getAttHeight());
        }
        courseVo.setStatus(coursePackage.getStatus() == 0 ? false : true);
        if("en".equals(language)){
            courseVo.setIntroduction(coursePackage.getBriefIntroductionEn());
            courseVo.setName(coursePackage.getNameEn());
        }else{
            courseVo.setIntroduction(coursePackage.getBriefIntroduction());
            courseVo.setName(coursePackage.getName());
        }
        // TODO: 2022/9/23 根据课程类型id查询课程类型
        if("en".equals(language)){
            courseVo.setTypeName(categoryService.getById(coursePackage.getCourseTypeId()).getNameEn());
        }else{
            courseVo.setTypeName(categoryService.getById(coursePackage.getCourseTypeId()).getName());
        }
        courseVo.setTypeLabelColor(categoryService.getById(coursePackage.getCourseTypeId()).getLabelColor());
        courseVo.setDuration(coursePackage.getDurationTotal());
        HashMap<String, Object> priceMap = systemGroupDataService.getMapByGid(SysGroupDataConstants.GROUP_DATA_ID_CLIENT_COURSE_PRICE, coursePackage.getCoursePackagePriceId());
        String coursePrice = String.valueOf(priceMap.get("coursePrice"));
        courseVo.setPrice(new BigDecimal(coursePrice));
        courseVo.setCarouselMap(JSONArray.parseArray(coursePackage.getCarouselChart()));
        if("en".equals(language)){
            courseVo.setCourseInfo(JSONArray.parseArray(coursePackage.getDetailsEn()));
        }else{
            courseVo.setCourseInfo(JSONArray.parseArray(coursePackage.getDetails()));
        }
        // TODO: 2022/11/21 处理套课中的课程排期
        List<CourseSchedulingVo> courseSchedulingVos = new ArrayList<>();
        List<CoursePackageRelation> relationList = coursePackageRelationService.list(new LambdaQueryWrapper<CoursePackageRelation>().eq(CoursePackageRelation::getCoursePackageId, coursePackage.getId()));
        if (relationList.size() <= 0) {
            return null;
        }
        // TODO: 2022/11/28 判断当前课程是否被当前用户收藏
        if (user != null) {
            boolean collect = userCollectionService.count(new LambdaQueryWrapper<UserCollection>().eq(UserCollection::getUid, user.getUid()).eq(UserCollection::getMainType, Constants.ORDER_TYPE_PACKAGE).eq(UserCollection::getMainId, coursePackage.getId()).eq(UserCollection::getType, "collect").eq(UserCollection::getIsDeleted, false)) > 0;
            courseVo.setIsCollection(collect);
        }
        List<CourseVo> courseVos = new ArrayList<>();
//        Integer totalSeatsLeftForAllScheduledCourses = 0;
        List<Integer> totalSeats = new ArrayList<>();
        Integer orderQuantityToBeWrittenOff = 0;
        Integer completedOrderQuantity = 0;
        for (CoursePackageRelation relation : relationList) {
            coursePackageId = relation.getCoursePackageId();
            CourseVo info = info(language,relation.getCourseId(), "info_one", request, Constants.ORDER_TYPE_PACKAGE);
            orderQuantityToBeWrittenOff = info.getOrderQuantityToBeWrittenOff();
            completedOrderQuantity = info.getCompletedOrderQuantity();
//            totalSeatsLeftForAllScheduledCourses += info.getTotalSeatsLeftForAllScheduledCourses();
            totalSeats.add(info.getTotalSeatsLeftForAllScheduledCourses());
            List<CourseSchedulingVo> schedulingList = info.getSchedulingList();
            for (CourseSchedulingVo courseSchedulingVo : schedulingList) {
                courseSchedulingVos.add(courseSchedulingVo);
            }
            courseVos.add(info);
        }
        courseVo.setOrderQuantityToBeWrittenOff(orderQuantityToBeWrittenOff);
        courseVo.setCompletedOrderQuantity(completedOrderQuantity);
        courseVo.setIsAppointment(completedOrderQuantity > 0 || orderQuantityToBeWrittenOff > 0 ? true : false);
        Collections.sort(totalSeats);
        courseVo.setTotalSeatsLeftForAllScheduledCourses(totalSeats.get(0));
        courseVo.setSchedulingList(courseSchedulingVos);
        // TODO: 2022/11/21 处理相关课程推荐
        List<CourseAbout> courseAboutList = getCourseAbout(1, 1, Math.toIntExact(coursePackage.getId()));
        List<CourseAboutResponse> courseAboutResponseList = new ArrayList<>();
        for (CourseAbout courseAbout : courseAboutList) {
            CourseAboutResponse courseAboutResponse = new CourseAboutResponse();
            courseAboutResponse = processRelevantCourseInformation(language,courseAbout);
            if (courseAboutResponse == null) {
                continue;
            }
            courseAboutResponseList.add(courseAboutResponse);
        }
        courseVo.setEventRecommendations(courseAboutResponseList);
        // TODO: 2022/10/18 处理你可能喜欢的商品 推荐
        List<CourseAbout> courseMayLikeList = getCourseAbout(2, 1, Math.toIntExact(coursePackage.getId()));
        List<CourseAboutResponse> courseMayLikeResponseList = new ArrayList<>();
        for (CourseAbout courseMayLike : courseMayLikeList) {
            CourseAboutResponse courseMayLikeResponse = new CourseAboutResponse();
            BeanUtils.copyProperties(courseMayLike, courseMayLikeResponse);
            courseMayLikeResponse = processRelevantCourseInformation(language,courseMayLike);
            if (courseMayLikeResponse == null) {
                continue;
            }
            courseMayLikeResponseList.add(courseMayLikeResponse);
        }
        courseVo.setShopRecommendations(courseMayLikeResponseList);
        courseVo.setCover(coursePackage.getCoverImage());
        // TODO: 2022/11/21 设置课程类型为套课
        courseVo.setType(1);
        return courseVo;
    }

    /**
     * @Description:处理响应结果排序和分页
     * @Author: chenBing
     * @Date: 2022/9/26
     */
    public PageInfo<CourseVo> fenYe(List<CourseVo> courseResponseList, PageParamRequest pageParamRequest) {
        //给list集合排序
        // TODO: 2022/9/26 排序规则：现根据上课日期升序，再根据上课开始时间升序，再根据剩余席位升序
        courseResponseList = courseResponseList.stream().sorted(Comparator.comparing(CourseVo::getType).thenComparing(Comparator.comparing(CourseVo::getSchedulingDate)).thenComparing(Comparator.comparing(CourseVo::getSchedulingStartTime)).thenComparing(Comparator.comparing(CourseVo::getSchedulingSeatCount).reversed())).collect(Collectors.toList());
        return startPage(courseResponseList, pageParamRequest.getPage(), pageParamRequest.getLimit());
    }

    /**
     * @Description:分页
     * @Author: chenBing
     * @Date: 2022/9/26
     */
    public <T> PageInfo<T> startPage(List<T> list, Integer pageNum, Integer pageSize) {
        //创建Page类
        com.github.pagehelper.Page page = new com.github.pagehelper.Page(pageNum, pageSize);
        //为Page类中的total属性赋值
        page.setTotal(list.size());
        //计算当前需要显示的数据下标起始值
        int startIndex = (pageNum - 1) * pageSize;
        int endIndex = Math.min(startIndex + pageSize, list.size());
        //从链表中截取需要显示的子链表，并加入到Page
        if (startIndex < endIndex) {
            page.addAll(list.subList(startIndex, endIndex));
        }
        //以Page创建PageInfo
        PageInfo pageInfo = new PageInfo<>(page);
        return pageInfo;
    }

    /**
     * @Description:课程详情
     * @Author: chenBing
     * @Date: 2022/9/23
     */
    @Override
    public CourseVo info(String language,Long courseId) {
        return info(language,courseId, "info_one", null, Constants.ORDER_TYPE_COURSE);
    }

    /**
     * @Description:课程详情
     * @Author: chenBing
     * @Date: 2022/9/23
     */
    public CourseVo info(String language,Long courseId, String type, CourseFilterRequest request, Integer courseType) {
        User user = userService.getInfo();
        Course c = getById(courseId);
        if (c == null) {
            log.debug("未查询到courseId为【" + courseId + "】的课程");
            return null;
        }
        CourseVo courseVo = new CourseVo();
        BeanUtils.copyProperties(c, courseVo);
        if (StringUtils.isNotBlank(c.getMainPictureVideo())) {
            SystemAttachment systemAttachment = systemAttachmentService.getOne(new LambdaQueryWrapper<SystemAttachment>().eq(SystemAttachment::getSattDir, c.getMainPictureVideo()));
            courseVo.setMainPictureVideoWidth(systemAttachment.getAttWidth());
            courseVo.setMainPictureVideoHeight(systemAttachment.getAttHeight());
        }
        // TODO: 2022/11/28 判断当前课程是否被当前用户收藏
        if (user != null) {
            boolean collect = userCollectionService.count(new LambdaQueryWrapper<UserCollection>().eq(UserCollection::getUid, user.getUid()).eq(UserCollection::getMainType, Constants.ORDER_TYPE_COURSE).eq(UserCollection::getMainId, c.getId()).eq(UserCollection::getType, "collect").eq(UserCollection::getIsDeleted, false)) > 0;
            courseVo.setIsCollection(collect);
        }
        // TODO: 2022/9/28 修改课程轮播图
        JSONArray courseCarouselMap = JSONArray.parseArray(c.getCarouselMap() == null ? "" : c.getCarouselMap());
        courseVo.setCarouselMap(courseCarouselMap);
        // TODO: 2022/9/23 根据课程类型id查询课程类型
        if("en".equals(language)){
            courseVo.setTypeName(categoryService.getById(c.getCourseTypeId()).getNameEn());
            courseVo.setName(courseVo.getNameEn());
            courseVo.setIntroduction(courseVo.getIntroductionEn());
        }else{
            courseVo.setTypeName(categoryService.getById(c.getCourseTypeId()).getName());
        }
        courseVo.setTypeLabelColor(categoryService.getById(c.getCourseTypeId()).getLabelColor());
        // TODO: 2022/9/23 课程当前所排的课程
        LambdaQueryWrapper<CourseScheduling> courseLqw = new LambdaQueryWrapper<>();
        int day = Integer.parseInt(systemConfigService.getValueByKey(Constants.COURSE_SHOW_DAY));
        String dateToTenDayDate = DateUtil.format(DateUtil.offset(new Date(), DateField.DAY_OF_YEAR, day), "yyyy-MM-dd");
        courseLqw.eq(CourseScheduling::getCourseId, c.getId()).eq(CourseScheduling::getIsDel, false).eq(CourseScheduling::getIsCancel, false).eq(CourseScheduling::getStatus, true).between(CourseScheduling::getSchedulingDate, DateUtil.format(new Date(), "yyyy-MM-dd"), dateToTenDayDate).orderByAsc(CourseScheduling::getSchedulingDate).orderByAsc(CourseScheduling::getSchedulingStartTime);
        if (ObjectUtil.isNotNull(request)) {
            if (StringUtils.isNotBlank(request.getDate())) {
                courseLqw.eq(CourseScheduling::getSchedulingDate, request.getDate());
            }
        }
        List<CourseScheduling> courseSchedulingList = courseSchedulingService.list(courseLqw);
        List<CourseScheduling> courseSchedulings = new ArrayList<>();
        for (CourseScheduling courseScheduling : courseSchedulingList) {
            if (courseScheduling.getSchedulingDate().compareTo(DateUtil.format(new Date(), "yyyy-MM-dd")) == 0) {
                String format = DateUtil.format(new Date(), "HH:mm");
                if (courseScheduling.getSchedulingStartTime().compareTo(format) <= -1) {
                    courseSchedulings.add(courseScheduling);
                }
            }
        }
        courseSchedulingList.removeAll(courseSchedulings);
        List<CourseSchedulingVo> courseSchedulingVos = new ArrayList<>();
        CourseSchedulingVo courseSchedulingVo = new CourseSchedulingVo();
        List<CourseSchedulingVo.Scheduling> schedulings = new ArrayList<>();
        Integer totalSeatsLeftForAllScheduledCourses = 0;
        for (CourseScheduling courseScheduling : courseSchedulingList) {
            CourseSchedulingVo.Scheduling scheduling = new CourseSchedulingVo.Scheduling();
            BeanUtils.copyProperties(courseScheduling, scheduling);
            HashMap<String, Object> courseLanguageMap = systemGroupDataService.getMapByGid(SysGroupDataConstants.GROUP_DATA_ID_CLIENT_COURSE_LANGUAGE, courseScheduling.getCourseLanguageId());
            String courseLanguage = "";
            if("en".equals(language)){
                courseLanguage = String.valueOf(courseLanguageMap.get("courseLanguageEn"));
            }else{
                courseLanguage = String.valueOf(courseLanguageMap.get("courseLanguage"));
            }
            scheduling.setLanguage(courseLanguage);
            scheduling.setRemainingSeatCount(courseScheduling.getExternalLimit());
            HashMap<String, Object> priceMap = systemGroupDataService.getMapByGid(SysGroupDataConstants.GROUP_DATA_ID_CLIENT_COURSE_PRICE, courseScheduling.getPriceId());
            String coursePrice = String.valueOf(priceMap.get("coursePrice"));
            scheduling.setPrice(new BigDecimal(coursePrice));
            scheduling.setSchedulingId(courseScheduling.getId());
            scheduling.setIsDel(courseScheduling.getIsDel());
            scheduling.setStatus(courseScheduling.getStatus());
            scheduling.setSchedulingStatus(com.vca.common.utils.DateUtil.getSchedulingStatus(courseScheduling.getSchedulingDate(), courseScheduling.getSchedulingStartTime(), courseScheduling.getSchedulingEndTime()));

            totalSeatsLeftForAllScheduledCourses += courseScheduling.getExternalLimit();
            // TODO: 2022/12/6 判断当前预约是否已截止
            Integer courseEndOrderTimeHour = Integer.valueOf(systemConfigService.getValueByKey(Constants.EXHIBITION_END_ORDER_TIME));
            Date schedulingDate = com.vca.common.utils.DateUtil.strToDate(courseScheduling.getSchedulingDate() + " " + courseScheduling.getSchedulingStartTime() + ":00", "yyyy-MM-dd HH:mm:ss");
            DateTime offset = cn.hutool.core.date.DateUtil.offset(schedulingDate, DateField.HOUR, -courseEndOrderTimeHour);
            long between = cn.hutool.core.date.DateUtil.between(offset, cn.hutool.core.date.DateUtil.date(), DateUnit.SECOND, false);
            if (between >= 0) {
                scheduling.setIsStopAppointment(true);
            }
            schedulings.add(scheduling);
        }
        courseVo.setTotalSeatsLeftForAllScheduledCourses(totalSeatsLeftForAllScheduledCourses);
        HashMap<String, Object> courseAddressMap = systemGroupDataService.getMapByGid(SysGroupDataConstants.GROUP_DATA_ID_CLIENT_COURSE_ADDRESS, c.getCourseAddressId());
        Object courseAddress = "";
        Object courseAddressInfo = "";
        Object dest = "";
        if("en".equals(language)){
            courseAddress = courseAddressMap.get("courseAddressEn");
            courseAddressInfo = courseAddressMap.get("courseAddressInfoEn");
            dest = courseAddressMap.get("destEn");
        }else{
            courseAddress = courseAddressMap.get("courseAddress");
            courseAddressInfo = courseAddressMap.get("courseAddressInfo");
            dest = courseAddressMap.get("dest");
        }

        Object lat = courseAddressMap.get("lat");
        Object lon = courseAddressMap.get("lon");
        HashMap<String, Object> courseAddressInfoMap = new HashMap<>();
        courseAddressInfoMap.put("courseAddress", courseAddress);
        courseAddressInfoMap.put("courseAddressInfo", courseAddressInfo);
        courseAddressInfoMap.put("lat", lat);
        courseAddressInfoMap.put("lon", lon);
        courseAddressInfoMap.put("dest", dest);
        courseAddressInfoMap.put("addressId", c.getCourseAddressId());
        courseSchedulingVo.setAddress(courseAddressInfoMap);
        courseSchedulingVo.setCourseId(c.getId());
        if("en".equals(language)){
            courseSchedulingVo.setName(c.getNameEn());
        }else{
            courseSchedulingVo.setName(c.getName());
        }
        courseSchedulingVo.setSchedulings(schedulings);
        courseSchedulingVos.add(courseSchedulingVo);
        courseVo.setSchedulingList(courseSchedulingVos);
        // TODO: 2022/9/23 根据课程id查询排课课程
        courseLqw.ge(CourseScheduling::getSchedulingDate, DateUtil.format(DateUtil.beginOfDay(new Date()), "yyyy-MM-dd"));
        List<CourseScheduling> schedulingList = courseSchedulingService.list(courseLqw);
        if (schedulingList.size() > 0) {
            courseVo = checkScheduling(language,courseVo, schedulingList, c);
        } else if (type.equals("info_list")) {
            return null;
        }
        // TODO: 2022/9/23 处理课程时长
        HashMap<String, Object> courseDurationMap = systemGroupDataService.getMapByGid(SysGroupDataConstants.GROUP_DATA_ID_CLIENT_COURSE_DURATION, c.getCourseDurationId());
        BigDecimal courseDuration = new BigDecimal(String.valueOf(courseDurationMap.get("courseDuration")));
        courseVo.setDuration(courseDuration);
        // TODO: 2022/9/22 设置课程详情
        CourseInfo courseInfo = courseInfoService.getOne(new LambdaQueryWrapper<CourseInfo>().eq(CourseInfo::getCourseId, c.getId()));
        if("en".equals(language)){
            courseVo.setCourseInfo(JSONObject.parseArray(courseInfo.getDetailsEn()));
        }else{
            courseVo.setCourseInfo(JSONObject.parseArray(courseInfo.getDetails()));
        }
        // TODO: 2022/9/23 处理相关课程推荐
        courseVo.setEventRecommendations(getCourseAbouts(language,1, 0, Math.toIntExact(courseId)));
        // TODO: 2022/10/18 处理你可能喜欢的商品 推荐
        courseVo.setShopRecommendations(getCourseAbouts(language,2, 0, Math.toIntExact(courseId)));
        // TODO: 2022/12/1 处理相关出版物推荐
        courseVo.setPublicationRecommendations(getCourseAbouts(language,3, 0, Math.toIntExact(courseId)));
        // TODO: 2022/11/28 判断用户是否预约过当前课程的排期
        Integer orderQuantityToBeWrittenOff = 0;
        Integer completedOrderQuantity = 0;
        //todo : 根据当前课程查询所有排期.
        if (user != null) {
            List<CourseScheduling> appointmentSchedulings = courseSchedulingService.list(new LambdaQueryWrapper<CourseScheduling>().eq(CourseScheduling::getCourseId, c.getId()));
            for (CourseScheduling courseScheduling : appointmentSchedulings) {
                if (courseType == 1) {
                    HashMap<String, Object> map = vcaOrderService.checkPersonAppointment(user, c, courseScheduling, Constants.ORDER_TYPE_PACKAGE, coursePackageId);
                    orderQuantityToBeWrittenOff += (Integer) map.get("orderQuantityToBeWrittenOff");
                    completedOrderQuantity += (Integer) map.get("completedOrderQuantity");
                } else {
                    HashMap<String, Object> map = vcaOrderService.checkPersonAppointment(user, c, courseScheduling, Constants.ORDER_TYPE_COURSE, coursePackageId);
                    orderQuantityToBeWrittenOff += (Integer) map.get("orderQuantityToBeWrittenOff");
                    completedOrderQuantity += (Integer) map.get("completedOrderQuantity");
                }
            }
        }
        courseVo.setOrderQuantityToBeWrittenOff(orderQuantityToBeWrittenOff);
        courseVo.setCompletedOrderQuantity(completedOrderQuantity);
        courseVo.setIsAppointment(orderQuantityToBeWrittenOff > 0 || completedOrderQuantity > 0 ? true : false);
        boolean isZero = true;
        if (courseVo.getSchedulingList().size() > 0) {
            for (CourseSchedulingVo schedulingVo : courseVo.getSchedulingList()) {
                if (schedulingVo.getSchedulings().size() > 0) {
                    isZero = false;
                }
            }
        }
        if (isZero) {
            HashMap<String, Object> priceMap = systemGroupDataService.getMapByGid(SysGroupDataConstants.GROUP_DATA_ID_CLIENT_COURSE_PRICE, c.getCoursePriceId());
            String coursePrice = String.valueOf(priceMap.get("coursePrice"));
            courseVo.setPrice(new BigDecimal(coursePrice));
        }
        return courseVo;
    }


    public CourseVo infoS(Long courseId, String type) {
        User user = userService.getInfo();
        Course c = getById(courseId);
        if (c == null) {
            log.debug("未查询到courseId为【" + courseId + "】的课程");
            return null;
        }
        CourseVo courseVo = new CourseVo();
        BeanUtils.copyProperties(c, courseVo);
        // TODO: 2022/9/23 课程当前所排的课程
        LambdaQueryWrapper<CourseScheduling> courseLqw = new LambdaQueryWrapper<>();
        int day = Integer.parseInt(systemConfigService.getValueByKey(Constants.COURSE_SHOW_DAY));
        String dateToTenDayDate = DateUtil.format(DateUtil.offset(new Date(), DateField.DAY_OF_YEAR, day), "yyyy-MM-dd");
        courseLqw.eq(CourseScheduling::getCourseId, c.getId()).eq(CourseScheduling::getIsDel, false).eq(CourseScheduling::getIsCancel, false).eq(CourseScheduling::getStatus, true).between(CourseScheduling::getSchedulingDate, DateUtil.format(new Date(), "yyyy-MM-dd"), dateToTenDayDate).orderByAsc(CourseScheduling::getSchedulingDate).orderByAsc(CourseScheduling::getSchedulingStartTime);
        List<CourseScheduling> courseSchedulingList = courseSchedulingService.list(courseLqw);
        List<CourseScheduling> courseSchedulings = new ArrayList<>();
        for (CourseScheduling courseScheduling : courseSchedulingList) {
            if (courseScheduling.getSchedulingDate().compareTo(DateUtil.format(new Date(), "yyyy-MM-dd")) == 0) {
                String format = DateUtil.format(new Date(), "HH:mm");
                if (courseScheduling.getSchedulingStartTime().compareTo(format) <= -1) {
                    courseSchedulings.add(courseScheduling);
                }
            }
        }
        courseSchedulingList.removeAll(courseSchedulings);
        List<CourseSchedulingVo> courseSchedulingVos = new ArrayList<>();
        CourseSchedulingVo courseSchedulingVo = new CourseSchedulingVo();
        List<CourseSchedulingVo.Scheduling> schedulings = new ArrayList<>();
        Integer totalSeatsLeftForAllScheduledCourses = 0;
        for (CourseScheduling courseScheduling : courseSchedulingList) {
            CourseSchedulingVo.Scheduling scheduling = new CourseSchedulingVo.Scheduling();
            BeanUtils.copyProperties(courseScheduling, scheduling);
            HashMap<String, Object> courseLanguageMap = systemGroupDataService.getMapByGid(SysGroupDataConstants.GROUP_DATA_ID_CLIENT_COURSE_LANGUAGE, courseScheduling.getCourseLanguageId());
            String courseLanguage = String.valueOf(courseLanguageMap.get("courseLanguage"));
            scheduling.setLanguage(courseLanguage);
            scheduling.setRemainingSeatCount(courseScheduling.getExternalLimit());
            HashMap<String, Object> priceMap = systemGroupDataService.getMapByGid(SysGroupDataConstants.GROUP_DATA_ID_CLIENT_COURSE_PRICE, courseScheduling.getPriceId());
            String coursePrice = String.valueOf(priceMap.get("coursePrice"));
            scheduling.setPrice(new BigDecimal(coursePrice));
            scheduling.setSchedulingId(courseScheduling.getId());
            scheduling.setIsDel(courseScheduling.getIsDel());
            scheduling.setStatus(courseScheduling.getStatus());
            scheduling.setSchedulingStatus(com.vca.common.utils.DateUtil.getSchedulingStatus(courseScheduling.getSchedulingDate(), courseScheduling.getSchedulingStartTime(), courseScheduling.getSchedulingEndTime()));

            totalSeatsLeftForAllScheduledCourses += courseScheduling.getExternalLimit();
            // TODO: 2022/12/6 判断当前预约是否已截止
            Integer courseEndOrderTimeHour = Integer.valueOf(systemConfigService.getValueByKey(Constants.EXHIBITION_END_ORDER_TIME));
            Date schedulingDate = com.vca.common.utils.DateUtil.strToDate(courseScheduling.getSchedulingDate() + " " + courseScheduling.getSchedulingStartTime() + ":00", "yyyy-MM-dd HH:mm:ss");
            DateTime offset = cn.hutool.core.date.DateUtil.offset(schedulingDate, DateField.HOUR, -courseEndOrderTimeHour);
            long between = cn.hutool.core.date.DateUtil.between(offset, cn.hutool.core.date.DateUtil.date(), DateUnit.SECOND, false);
            if (between >= 0) {
                scheduling.setIsStopAppointment(true);
            }
            schedulings.add(scheduling);
        }
        courseVo.setTotalSeatsLeftForAllScheduledCourses(totalSeatsLeftForAllScheduledCourses);
        HashMap<String, Object> courseAddressMap = systemGroupDataService.getMapByGid(SysGroupDataConstants.GROUP_DATA_ID_CLIENT_COURSE_ADDRESS, c.getCourseAddressId());
        Object courseAddress = courseAddressMap.get("courseAddress");
        Object courseAddressInfo = courseAddressMap.get("courseAddressInfo");
        Object lat = courseAddressMap.get("lat");
        Object lon = courseAddressMap.get("lon");
        Object dest = courseAddressMap.get("dest");
        HashMap<String, Object> courseAddressInfoMap = new HashMap<>();
        courseAddressInfoMap.put("courseAddress", courseAddress);
        courseAddressInfoMap.put("courseAddressInfo", courseAddressInfo);
        courseAddressInfoMap.put("lat", lat);
        courseAddressInfoMap.put("lon", lon);
        courseAddressInfoMap.put("dest", dest);
        courseAddressInfoMap.put("addressId", c.getCourseAddressId());
        courseSchedulingVo.setAddress(courseAddressInfoMap);
        courseSchedulingVo.setCourseId(c.getId());
        courseSchedulingVo.setName(c.getName());
        courseSchedulingVo.setSchedulings(schedulings);
        courseSchedulingVos.add(courseSchedulingVo);
        courseVo.setSchedulingList(courseSchedulingVos);
        // TODO: 2022/9/23 根据课程id查询排课课程
        courseLqw.ge(CourseScheduling::getSchedulingDate, DateUtil.format(DateUtil.beginOfDay(new Date()), "yyyy-MM-dd"));
        List<CourseScheduling> schedulingList = courseSchedulingService.list(courseLqw);
        if (schedulingList.size() > 0) {
            courseVo = getPriceOfCourse(courseVo, schedulingList, c);
        } else {
            return null;
        }
        boolean isZero = true;
        if (courseVo.getSchedulingList().size() > 0) {
            for (CourseSchedulingVo schedulingVo : courseVo.getSchedulingList()) {
                if (schedulingVo.getSchedulings().size() > 0) {
                    isZero = false;
                }
            }
        }
        if (isZero) {
            HashMap<String, Object> priceMap = systemGroupDataService.getMapByGid(SysGroupDataConstants.GROUP_DATA_ID_CLIENT_COURSE_PRICE, c.getCoursePriceId());
            String coursePrice = String.valueOf(priceMap.get("coursePrice"));
            courseVo.setPrice(new BigDecimal(coursePrice));
        }
        return courseVo;
    }

    @Override
    public List<CourseAboutResponse> getCourseAbouts(String language,Integer type, Integer typeMainCourse, Integer mainId) {
        List<CourseAbout> courseAboutList = getCourseAbout(type, typeMainCourse, mainId);
        List<CourseAboutResponse> courseAboutResponseList = new ArrayList<>();
        for (CourseAbout courseAbout : courseAboutList) {
            CourseAboutResponse courseAboutResponse = new CourseAboutResponse();
            courseAboutResponse = processRelevantCourseInformation(language,courseAbout);
            if (courseAboutResponse == null) {
                continue;
            }
            courseAboutResponseList.add(courseAboutResponse);
        }
        courseAboutResponseList = courseAboutResponseList.stream().sorted(Comparator.comparing(CourseAboutResponse::getSort).reversed()).collect(Collectors.toList());
        return courseAboutResponseList;
    }

    private CourseVo checkScheduling(String language,CourseVo courseVo, List<CourseScheduling> schedulings, Course c) {
        DateTime date = DateUtil.date();
        SchedulingVo schedulingV = new SchedulingVo();
        schedulingV.setScheduled(0L);
        schedulingV.setScheduledDateTime(date);
        List<SchedulingVo> schedulingVos = new ArrayList<>();
        for (CourseScheduling scheduling : schedulings) {
            SchedulingVo schedulingVo = new SchedulingVo();
            // TODO: 2022/11/25 yyyy-MM-dd HH:mm:ss
            String schedulingDate = scheduling.getSchedulingDate() + " " + scheduling.getSchedulingStartTime();
            DateTime dateTime = DateUtil.parse(schedulingDate, "yyyy-MM-dd HH:mm");
            schedulingVo.setScheduledDateTime(dateTime);
            schedulingVo.setScheduled(scheduling.getId());
            schedulingVos.add(schedulingVo);
        }
        schedulingVos.add(schedulingV);
        schedulingVos = schedulingVos.stream().sorted(Comparator.comparing(SchedulingVo::getScheduledDateTime)).collect(Collectors.toList());
        Long scheduledId = 0L;
        for (int i = 0; i < schedulingVos.size(); i++) {
            if (schedulingVos.get(i).getScheduled() == 0 && i + 1 < schedulingVos.size()) {
                scheduledId = schedulingVos.get(i + 1).getScheduled();
            }
        }
        if (scheduledId == 0) {
            return courseVo;
        }
        CourseScheduling courseScheduling = courseSchedulingService.getById(scheduledId);
        courseVo.setSchedulingDate(courseScheduling.getSchedulingDate());
        courseVo.setSchedulingStartTime(courseScheduling.getSchedulingStartTime());
        courseVo.setSchedulingEndTime(courseScheduling.getSchedulingEndTime());
        courseVo.setSchedulingSeatCount(courseScheduling.getExternalLimit());

        HashMap<String, Object> courseLanguageMap = systemGroupDataService.getMapByGid(SysGroupDataConstants.GROUP_DATA_ID_CLIENT_COURSE_LANGUAGE, courseScheduling.getCourseLanguageId());

        String courseLanguage = "";
        if("en".equals(language)){
            courseLanguage = String.valueOf(courseLanguageMap.get("courseLanguageEn"));
        }else{
            courseLanguage = String.valueOf(courseLanguageMap.get("courseLanguage"));
        }
        courseScheduling.setCourseLanguageName(courseLanguage);
        courseVo.setLanguage(courseLanguage);
        HashMap<String, Object> priceMap = systemGroupDataService.getMapByGid(SysGroupDataConstants.GROUP_DATA_ID_CLIENT_COURSE_PRICE, courseScheduling.getPriceId());
        String coursePrice = String.valueOf(priceMap.get("coursePrice"));
        courseVo.setPrice(new BigDecimal(coursePrice));
        return courseVo;
    }

    private CourseVo getPriceOfCourse(CourseVo courseVo, List<CourseScheduling> schedulings, Course c) {
        DateTime date = DateUtil.date();
        SchedulingVo schedulingV = new SchedulingVo();
        schedulingV.setScheduled(0L);
        schedulingV.setScheduledDateTime(date);
        List<SchedulingVo> schedulingVos = new ArrayList<>();
        for (CourseScheduling scheduling : schedulings) {
            SchedulingVo schedulingVo = new SchedulingVo();
            // TODO: 2022/11/25 yyyy-MM-dd HH:mm:ss
            String schedulingDate = scheduling.getSchedulingDate() + " " + scheduling.getSchedulingStartTime();
            DateTime dateTime = DateUtil.parse(schedulingDate, "yyyy-MM-dd HH:mm");
            schedulingVo.setScheduledDateTime(dateTime);
            schedulingVo.setScheduled(scheduling.getId());
            schedulingVos.add(schedulingVo);
        }
        schedulingVos.add(schedulingV);
        schedulingVos = schedulingVos.stream().sorted(Comparator.comparing(SchedulingVo::getScheduledDateTime)).collect(Collectors.toList());
        Long scheduledId = 0L;
        for (int i = 0; i < schedulingVos.size(); i++) {
            if (schedulingVos.get(i).getScheduled() == 0 && i + 1 < schedulingVos.size()) {
                scheduledId = schedulingVos.get(i + 1).getScheduled();
            }
        }
        if (scheduledId == 0) {
            return courseVo;
        }
        CourseScheduling courseScheduling = courseSchedulingService.getById(scheduledId);
        HashMap<String, Object> priceMap = systemGroupDataService.getMapByGid(SysGroupDataConstants.GROUP_DATA_ID_CLIENT_COURSE_PRICE, courseScheduling.getPriceId());
        String coursePrice = String.valueOf(priceMap.get("coursePrice"));
        courseVo.setPrice(new BigDecimal(coursePrice));
        return courseVo;
    }

    /**
     * @param selectId 当前查询的主键ID
     * @Description:获取相关课程或可能喜欢的商品
     * @Author: chenBing
     * @Date: 2022/11/3
     */
    @Override
    public List<CourseAbout> getCourseAbout(Integer type, Integer typeMainCourse, Integer selectId) {
        LambdaQueryWrapper<CourseAbout> lqw = new LambdaQueryWrapper<CourseAbout>().eq(CourseAbout::getIsDeleted, false).eq(CourseAbout::getType, type).eq(CourseAbout::getAboutMainId, Long.valueOf(selectId)).eq(CourseAbout::getTypeMainCourse, typeMainCourse).orderByAsc(CourseAbout::getSort);
        List<CourseAbout> courseAboutList = courseAboutService.list(lqw);
        return courseAboutList;
    }

    /**
     * @Description:处理相关课程信息
     * @Author: chenBing
     * @Date: 2022/11/3
     */
    @Override
    public CourseAboutResponse processRelevantCourseInformation(String language,CourseAbout courseAbout) {
        CourseAboutResponse courseAboutResponse = new CourseAboutResponse();
        BeanUtils.copyProperties(courseAbout, courseAboutResponse);
        switch (courseAbout.getTypeCourse()) {
            //课程
            case 0:
                Course course = getById(courseAbout.getAboutId());
                if (!course.getStatus()) {
                    return null;
                }
                courseAboutResponse.setSharePoster(course.getSharePoster());
                courseAboutResponse.setAboutId(courseAbout.getAboutId());
                courseAboutResponse.setCover(course.getCover());
                if("en".equals(language)){
                    courseAboutResponse.setName(course.getNameEn());
                    courseAboutResponse.setTypeName(categoryService.getById(course.getCourseTypeId()).getNameEn());
                }else{
                    courseAboutResponse.setName(course.getName());
                    courseAboutResponse.setTypeName(categoryService.getById(course.getCourseTypeId()).getName());
                }
                // TODO: 2022/9/23 根据课程类型id查询课程类型
                courseAboutResponse.setLabelColor(categoryService.getById(course.getCourseTypeId()).getLabelColor());
                CourseVo courseVo = infoS(course.getId(), "info_one");
                if (courseVo != null) {
                    courseAboutResponse.setPrice(courseVo.getPrice());
                } else {
                    HashMap<String, Object> priceMap = systemGroupDataService.getMapByGid(SysGroupDataConstants.GROUP_DATA_ID_CLIENT_COURSE_PRICE, course.getCoursePriceId());
                    String coursePrice = String.valueOf(priceMap.get("coursePrice"));
                    courseAboutResponse.setPrice(new BigDecimal(coursePrice));
                }
                break;
            //套课
            case 1:
                CoursePackage coursePackage = coursePackageService.getById(courseAbout.getAboutId());
                if (coursePackage.getStatus() == 0) {
                    return null;
                }
                courseAboutResponse.setSharePoster(coursePackage.getSharePoster());
                courseAboutResponse.setAboutId(courseAbout.getAboutId());
                courseAboutResponse.setCover(coursePackage.getCoverImage());
                if("en".equals(language)){
                    courseAboutResponse.setName(coursePackage.getNameEn());
                }else{
                    courseAboutResponse.setName(coursePackage.getName());
                }
                HashMap<String, Object> mp = systemGroupDataService.getMapByGid(SysGroupDataConstants.GROUP_DATA_ID_CLIENT_COURSE_PRICE, coursePackage.getCoursePackagePriceId());
                String price = String.valueOf(mp.get("coursePrice"));
                courseAboutResponse.setPrice(new BigDecimal(price));
                Category categoryVo = categoryService.getById(coursePackage.getCourseTypeId());

                if("en".equals(language)){
                    courseAboutResponse.setTypeName(categoryVo.getNameEn());
                }else{
                    courseAboutResponse.setTypeName(categoryVo.getName());
                }
                courseAboutResponse.setLabelColor(categoryVo.getLabelColor());
                break;
            //讲座
            case 2:
                Talk talk = talkService.getById(courseAbout.getAboutId());
                if (talk.getStatus() == 0) {
                    return null;
                }
                courseAboutResponse.setSharePoster(talk.getSharePoster());
                courseAboutResponse.setAboutId(courseAbout.getAboutId());
                courseAboutResponse.setCover(talk.getCoverImage());

                if("en".equals(language)){
                    courseAboutResponse.setName(talk.getNameEn());
                }else{
                    courseAboutResponse.setName(talk.getName());
                }
                TalkResponse talkInfo = talkService.infoS(talk.getId(), "talk_info_one", null);
                if (talkInfo != null) {
                    courseAboutResponse.setPrice(talkInfo.getPrice());
                } else {
                    courseAboutResponse.setPrice(talk.getPrice());
                }

                if("en".equals(language)){
                    courseAboutResponse.setTypeName(talk.getTalkType() == 1 ? "In-person Talk" : "Online Talk");
                }else{
                    courseAboutResponse.setTypeName(talk.getTalkType() == 1 ? "线下讲座" : "线上讲座");
                }

                courseAboutResponse.setLabelColor("#B4B19E");
                break;
            //展览
            case 3:
                Exhibition exhibition = exhibitionService.getById(courseAbout.getAboutId());
                if (exhibition.getStatus() == 0) {
                    return null;
                }
                courseAboutResponse.setSharePoster(exhibition.getSharePoster());
                courseAboutResponse.setAboutId(courseAbout.getAboutId());
                courseAboutResponse.setCover(exhibition.getCover());

                if("en".equals(language)){
                    courseAboutResponse.setName(exhibition.getNameEn());
                    courseAboutResponse.setTypeName(exhibition.getCityNameEn());
                }else{
                    courseAboutResponse.setName(exhibition.getName());
                    courseAboutResponse.setTypeName(exhibition.getCityName());
                }
                courseAboutResponse.setPrice(BigDecimal.ZERO);
                courseAboutResponse.setLabelColor("#B4B19E");
                break;
            //商品
            case 4:
                VcaProduct vcaProduct = vcaProductService.getById(courseAbout.getAboutId());
                if (!vcaProduct.getIsShow()) {
                    return null;
                }
                courseAboutResponse.setSharePoster(vcaProduct.getSharePoster());
                courseAboutResponse.setAboutId(courseAbout.getAboutId());
                courseAboutResponse.setCover(vcaProduct.getCoverImage());

                if("en".equals(language)){
                    courseAboutResponse.setName(vcaProduct.getNameEn());
                }else{
                    courseAboutResponse.setName(vcaProduct.getName());

                }
                courseAboutResponse.setPrice(vcaProduct.getPrice());
                Category category = categoryService.getById(vcaProduct.getCid());

                if("en".equals(language)){
                    courseAboutResponse.setTypeName(category.getNameEn());
                }else{
                    courseAboutResponse.setTypeName(category.getName());
                }
                courseAboutResponse.setLabelColor(category.getLabelColor());
                break;
            default:
                break;
        }
        return courseAboutResponse;
    }


    /**
     * @Description:新增课程
     * @Author: chenBing
     * @Date: 2022/11/7
     */
    @Override
    public Boolean addCourse(CourseAddRequest request) {
        //去除阿里云前缀
        List<String> carouselMaps = new ArrayList();
        request.getCarouselMap().forEach(e -> {
            carouselMaps.add(systemAttachmentService.clearPrefix(e));
        });
        Course course = new Course();
        BeanUtils.copyProperties(request, course);
        course.setStatus(false);
        if (ObjectUtil.isEmpty(course.getSort())) {
            course.setSort(0);
        }
        //去除阿里云前缀
        course.setCover(systemAttachmentService.clearPrefix(request.getCoverImage()));
        course.setCarouselMap(systemAttachmentService.clearPrefix(JSONArray.parseArray(JSON.toJSONString(carouselMaps)).toJSONString()));
        course.setMainPictureVideo(StringUtils.isNotBlank(request.getMainPictureVideo()) ? systemAttachmentService.clearPrefix(request.getMainPictureVideo()) : "");
        course.setSharePoster(systemAttachmentService.clearPrefix(request.getSharePoster()));
        List<CourseAbout> courseAboutList = new ArrayList();
        if (ObjectUtil.isNotEmpty(request.getCourseAboutAddRequests())) {
            //将相关课程和商品根据0 = 课程 1=讲座 2=展览 3=商品 进行分组
            Map<Integer, List<CourseAboutAddRequest>> listMap = request.getCourseAboutAddRequests().stream().collect(Collectors.groupingBy((CourseAboutAddRequest::getTypeCourse)));
            //校验添加的相关课程是否存在
            courseAboutService.checkWhetherCourseAbout(listMap);
        }


        //添加课程详情
        CourseInfo courseInfo = new CourseInfo();
        courseInfo.setDetails(systemAttachmentService.clearPrefix(request.getDetails()));
        courseInfo.setDetailsEn(systemAttachmentService.clearPrefix(request.getDetailsEn()));
        courseInfo.setIsDeleted(0);

        //事务
        return transactionTemplate.execute(e -> {
            //添加套课并获得 套课id
            save(course);
            List<CoursePackageRelation> coursePackageRelations = new ArrayList();
            //添加套课和相关课程或商品的关系
            if (ObjectUtil.isNotEmpty(request.getCourseAboutAddRequests())) {
                request.getCourseAboutAddRequests().forEach(g -> {
                    CourseAbout courseAbout = new CourseAbout();
                    BeanUtils.copyProperties(g, courseAbout);
                    if (ObjectUtil.isEmpty(g.getSort())) {
                        courseAbout.setSort(0);
                    }
                    courseAbout.setAboutMainId(course.getId());
                    courseAbout.setTypeMainCourse(0);
                    courseAboutList.add(courseAbout);
                });
                courseAboutService.addCourseAboutList(courseAboutList);
            }
            courseInfo.setCourseId(course.getId());
            courseInfoService.save(courseInfo);
            return Boolean.TRUE;
        });
    }


    @Override
    public PageInfo<CourseAdminListResponse> getAdminList(AdminCommonRequest request, PageParamRequest pageParamRequest) {
        List<CourseAdminListResponse> courseAdminList = new ArrayList<>();
        List<CourseAdminListResponse> adminList = new ArrayList<>();
        LambdaUpdateWrapper<Course> wrapper = new LambdaUpdateWrapper();
        wrapper.eq(Course::getIsDeleted, 0);
        if (ObjectUtil.isNotEmpty(request.getType())) {
            wrapper.eq(Course::getCourseTypeId, request.getType());
        }
        if (ObjectUtil.isNotEmpty(request.getDuration())) {
            wrapper.eq(Course::getCourseDurationId, request.getDuration());
        }
        if (ObjectUtil.isNotEmpty(request.getPrice())) {
            wrapper.eq(Course::getCoursePriceId, request.getPrice());
        }
        if (ObjectUtil.isNotEmpty(request.getStatus())) {
            wrapper.eq(Course::getStatus, request.getStatus());
        }
        if (ObjectUtil.isNotEmpty(request.getType())) {
            wrapper.eq(Course::getCourseTypeId, request.getType());
        }
        if (ObjectUtil.isNotEmpty(request.getKeywords())) {
            List<Integer> ids = dao.fuzzySearch(request.getKeywords());
            if (ObjectUtil.isEmpty(ids)) {
                return PageUtils.startPage(courseAdminList, pageParamRequest.getPage(), pageParamRequest.getLimit());
            }
            wrapper.in(Course::getId, ids);
        }
        Map<String, List<HashMap<String, Object>>> courseAdminConfig = systemGroupDataService.getCourseAdminConfig();
        List<HashMap<String, Object>> duration = courseAdminConfig.get("durationList");
        List<HashMap<String, Object>> price = courseAdminConfig.get("priceList");
        List<HashMap<String, Object>> address = courseAdminConfig.get("addressList");
        List<Category> categories = categoryService.list(new LambdaQueryWrapper<Category>().eq(Category::getType, CategoryConstants.CATEGORY_TYPE_COURSE));
        HashMap<String, String> info = systemConfigService.info(SysConfigConstants.CONFIG_FROM_ID_BASIC);
        List<Course> courses = dao.selectList(wrapper);
        courses.forEach(course -> {
            CourseAdminListResponse response = new CourseAdminListResponse();
            BeanUtils.copyProperties(course, response);
            response.setRatio(Double.valueOf(info.get("limit_ration")));
            response.setCoverImage(course.getCover());
            duration.forEach(e -> {
                Map map = JSON.parseObject(JSONObject.toJSONString(e), Map.class);
                if (map.get("id").equals(course.getCourseDurationId())) {
                    response.setCourseDuration(map.get("courseDuration").toString());
                }
            });
            price.forEach(e -> {
                Map map = JSON.parseObject(JSONObject.toJSONString(e), Map.class);
                if (map.get("id").equals(course.getCoursePriceId())) {
                    response.setPrice(map.get("coursePrice").toString());
                }
            });
            address.forEach(e -> {
                Map map = JSON.parseObject(JSONObject.toJSONString(e), Map.class);
                if (map.get("id").equals(course.getCourseAddressId())) {
                    response.setCourseAddress(map.get("courseAddress").toString() + map.get("courseAddressInfo").toString());
                }
            });
            categories.forEach(e -> {
                if (course.getCourseTypeId().equals(e.getId().longValue())) {
                    response.setCourseType(e.getName());
                }
            });
            // TODO: 2022/11/3 设置talkInfo
            CourseInfo courseInfo = courseInfoService.getOne(new LambdaQueryWrapper<CourseInfo>().eq(CourseInfo::getCourseId, course.getId()));
            CourseInfoVo courseInfoVo = new CourseInfoVo();
            BeanUtils.copyProperties(courseInfo, courseInfoVo);
            courseInfoVo.setDetails(JSONObject.parseArray(courseInfo.getDetails()));
            // TODO: 2022/10/10 设置相关图集部分
//            courseInfoVo.setRelatedAtlas(JSONObject.parseArray(courseInfo.getRelatedAtlas()));
            response.setCourseInfo(courseInfoVo);
            adminList.add(response);
        });
        courseAdminList = adminList;
        if (ObjectUtil.isNotEmpty(request.getCarePrice())) {
            courseAdminList = courseAdminList.stream().filter(c -> Integer.valueOf(c.getPrice()).equals(request.getCarePrice())).collect(Collectors.toList());
        }
        return PageUtils.startPage(courseAdminList.stream().sorted(Comparator.comparing(CourseAdminListResponse::getSort).reversed()).collect(Collectors.toList()), pageParamRequest.getPage(), pageParamRequest.getLimit());
    }

    /**
     * 课程排序清零
     *
     * @return
     * @author Li
     * @date 2022/11/17 09:47
     */
    @Override
    public boolean getSortClearZero() {
        LambdaQueryWrapper<Course> wrapper = new LambdaQueryWrapper();
        wrapper.eq(Course::getIsDeleted, 0);
        wrapper.eq(Course::getIsRecycle, 0);
        List<Course> courses = dao.selectList(wrapper);

        return transactionTemplate.execute(e -> {
            courses.forEach(c -> {
                c.setSort(0);
                dao.updateById(c);
            });
            return Boolean.TRUE;
        });
    }

    /**
     * 修改排序
     *
     * @param courseId 课程id
     * @param sort     排序
     * @return
     * @author Li
     * @date 2022/11/17 09:47
     */
    @Override
    public boolean updateSort(Integer courseId, Integer sort) {
        if (ObjectUtil.isEmpty(courseId)) {
            throw new VcaException("请选择课程");
        }
        LambdaQueryWrapper<Course> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Course::getIsDeleted, 0);
        wrapper.eq(Course::getId, courseId);
        Course course = dao.selectOne(wrapper);
        if (ObjectUtil.isEmpty(course)) {
            throw new VcaException("该课程不存在");
        }
        course.setSort(sort);
        return transactionTemplate.execute(e -> {
            dao.updateById(course);
            return Boolean.TRUE;
        });
    }

    /**
     * 修改排序
     *
     * @param courseId  课程id
     * @param seatCount 席位数量
     * @return
     * @author Li
     * @date 2022/11/17 09:47
     */
    @Override
    public boolean updateSeatCount(Integer courseId, Integer seatCount) {
        if (ObjectUtil.isEmpty(courseId)) {
            throw new VcaException("请选择课程");
        }
        LambdaQueryWrapper<Course> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Course::getIsDeleted, 0);
        wrapper.eq(Course::getId, courseId);
        Course course = dao.selectOne(wrapper);
        if (ObjectUtil.isEmpty(course)) {
            throw new VcaException("该课程不存在");
        }
        course.setSeatCount(seatCount);
        return transactionTemplate.execute(e -> {
            dao.updateById(course);
            return Boolean.TRUE;
        });
    }

    /**
     * 上架课程
     *
     * @param courseId 课程id
     * @return
     * @author Li
     * @date 2022/11/17 09:47
     */
    @Override
    public boolean courseOnShell(Integer courseId) {
        if (ObjectUtil.isEmpty(courseId)) {
            throw new VcaException("请选择课程");
        }
        LambdaQueryWrapper<Course> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Course::getIsDeleted, 0);
        wrapper.eq(Course::getId, courseId);
        Course course = dao.selectOne(wrapper);
        if (ObjectUtil.isEmpty(course)) {
            throw new VcaException("该课程不存在");
        }
        course.setStatus(true);
        return transactionTemplate.execute(e -> {
            dao.updateById(course);
            return Boolean.TRUE;
        });
    }

    /**
     * 下架课程
     *
     * @param courseId 课程id
     * @return
     * @author Li
     * @date 2022/11/17 09:47
     */
    @Override
    public boolean courseOffShell(Integer courseId) {
        if (ObjectUtil.isEmpty(courseId)) {
            throw new VcaException("请选择课程");
        }
        LambdaQueryWrapper<Course> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Course::getIsDeleted, 0);
        wrapper.eq(Course::getId, courseId);
        Course course = dao.selectOne(wrapper);
        if (ObjectUtil.isEmpty(course)) {
            throw new VcaException("该课程不存在");
        }
        course.setStatus(false);
        return transactionTemplate.execute(e -> {
            dao.updateById(course);
            return Boolean.TRUE;
        });
    }

    /**
     * 根据id获取课程信息
     *
     * @param courseId
     * @return
     * @author Li
     * @date 2022/11/22 10:25
     */
    @Override
    public CourseAdminResponse getCourse(Long courseId) {
        CourseAdminResponse response = new CourseAdminResponse();
        //查询课程是否存在
        LambdaQueryWrapper<Course> wrapper = new LambdaQueryWrapper();
        wrapper.eq(Course::getId, courseId);
        wrapper.eq(Course::getIsRecycle, 0);
        Course course = dao.selectOne(wrapper);
        if (ObjectUtil.isEmpty(course)) {
            throw new VcaException("课程不存在");
        }
        BeanUtils.copyProperties(course, response);
        response.setCoverImage(course.getCover());
        List<CourseAbout> courseAbouts = courseAboutService.list(new LambdaQueryWrapper<CourseAbout>().eq(CourseAbout::getAboutMainId, courseId).eq(CourseAbout::getIsDeleted, 0).eq(CourseAbout::getTypeMainCourse, 0));
        //将相关课程和商品根据0 = 课程 1=讲座 2=展览 3=商品 4=套课
        Map<Integer, List<CourseAbout>> listMap = courseAbouts.stream().collect(Collectors.groupingBy(e -> e.getTypeCourse()));
        //验证判断添加的相关课程和商品是否存在
        Map<String, List<HashMap<String, Object>>> courseAdminConfig = systemGroupDataService.getCourseAdminConfigAll();
        List<HashMap<String, Object>> duration = courseAdminConfig.get("durationList");
        List<HashMap<String, Object>> price = courseAdminConfig.get("priceList");
        List<HashMap<String, Object>> address = courseAdminConfig.get("addressList");
        //获得时长
        duration.forEach(e -> {
            Map map = JSON.parseObject(JSONObject.toJSONString(e), Map.class);
            if (map.get("id").equals(course.getCourseDurationId())) {
                response.setCourseDuration(map.get("courseDuration").toString());
            }
        });
        //获得价格
        price.forEach(e -> {
            Map map = JSON.parseObject(JSONObject.toJSONString(e), Map.class);
            if (map.get("id").equals(course.getCoursePriceId())) {
                response.setPrice(map.get("coursePrice").toString());
            }
        });
        //获得地址信息
        address.forEach(e -> {
            Map map = JSON.parseObject(JSONObject.toJSONString(e), Map.class);
            if (map.get("id").equals(course.getCourseAddressId())) {
                response.setCourseAddress(map.get("courseAddress").toString() + map.get("courseAddressInfo").toString());
            }
        });
        //课程详情
        CourseInfo courseInfo = courseInfoService.getOne(new LambdaQueryWrapper<CourseInfo>().eq(CourseInfo::getCourseId, courseId));
        response.setDetails(courseInfo.getDetails());
        response.setDetailsEn(courseInfo.getDetailsEn());
        //获得相关课程的信息
        List<CourseAboutAdminResponse> aboutList = courseAboutService.getAdminCourseAbout(listMap, courseAdminConfig);
        response.setCourseAboutAdminResponses(aboutList);
        return response;
    }

    /**
     * @param request
     * @Description:修改课程
     * @Author: Li
     * @Date: 2022/11/22 14:56
     */
    @Override
    public boolean updateCourse(CourseAddRequest request) {

        //去除阿里云前缀
        List<String> carouselMaps = new ArrayList();
        request.getCarouselMap().forEach(e -> {
            carouselMaps.add(systemAttachmentService.clearPrefix(e));
        });
        Course course = dao.selectOne(new LambdaQueryWrapper<Course>().eq(Course::getId, request.getId()).eq(Course::getIsDeleted, 0));
        if (ObjectUtil.isEmpty(course)) {
            throw new VcaException("该课程不存在");
        }
        BeanUtils.copyProperties(request, course);
        course.setStatus(false);
        if (ObjectUtil.isEmpty(course.getSort())) {
            course.setSort(0);
        }
        //去除阿里云前缀
        course.setCover(systemAttachmentService.clearPrefix(request.getCoverImage()));
        course.setCarouselMap(systemAttachmentService.clearPrefix(JSONArray.parseArray(JSON.toJSONString(carouselMaps)).toJSONString()));
        course.setMainPictureVideo(StringUtils.isNotBlank(request.getMainPictureVideo()) ? systemAttachmentService.clearPrefix(request.getMainPictureVideo()) : "");
        course.setSharePoster(systemAttachmentService.clearPrefix(request.getSharePoster()));
        List<CourseAbout> courseAboutList = new ArrayList();
        //将相关课程和商品根据0 = 课程 1=讲座 2=展览 3=商品 4=套课 进行分组
        Map<Integer, List<CourseAboutAddRequest>> listMap = request.getCourseAboutAddRequests().stream().collect(Collectors.groupingBy((CourseAboutAddRequest::getTypeCourse)));

        //校验添加的相关课程是否存在
        courseAboutService.checkWhetherCourseAbout(listMap);

        //添加课程详情
        CourseInfo courseInfo = courseInfoService.getOne(new LambdaQueryWrapper<CourseInfo>().eq(CourseInfo::getCourseId, request.getId()));
        courseInfo.setDetails(systemAttachmentService.clearPrefix(request.getDetails()));
        courseInfo.setDetailsEn(systemAttachmentService.clearPrefix(request.getDetailsEn()));
        if (ObjectUtil.isNotEmpty(request.getCourseAboutAddRequests())) {
            request.getCourseAboutAddRequests().forEach(g -> {
                CourseAbout courseAbout = new CourseAbout();
                BeanUtils.copyProperties(g, courseAbout);
                if (ObjectUtil.isEmpty(g.getSort())) {
                    courseAbout.setSort(0);
                }
                courseAbout.setAboutMainId(request.getId());
                courseAbout.setTypeMainCourse(0);
                if (ObjectUtil.isNotEmpty(g.getCourseAboutId())) {
                    courseAbout.setId(g.getCourseAboutId());
                }
                courseAboutList.add(courseAbout);
            });
        }
        //事务
        return transactionTemplate.execute(e -> {
            //添加课程并获得 课程id
            updateById(course);
            //添加套课和相关课程或商品的关系
            if (ObjectUtil.isNotEmpty(request.getCourseAboutAddRequests())) {
                courseAboutService.updateCourseAboutList(courseAboutList, request.getId());

            }
            courseInfoService.updateById(courseInfo);
            return Boolean.TRUE;
        });
    }

    /**
     * 获得课程头部数据
     *
     * @return
     * @author Li
     * @date 2022/11/23 09:16
     */
    @Override
    public List<AdminHeaderResponse> getHeader() {
        List<AdminHeaderResponse> headers = new ArrayList();
        AdminHeaderResponse active = new AdminHeaderResponse(0, "Active", 1, null);
        AdminHeaderResponse inActive = new AdminHeaderResponse(0, "InActive", 0, null);
        active.setCount(dao.selectList(new LambdaQueryWrapper<Course>().eq(Course::getStatus, 1).eq(Course::getIsDeleted, 0)).size());
        inActive.setCount(dao.selectList(new LambdaQueryWrapper<Course>().eq(Course::getStatus, 0).eq(Course::getIsDeleted, 0)).size());
        headers.add(active);
        headers.add(inActive);
        return headers;
    }

    /**
     * 删除课程
     *
     * @param id
     * @return
     * @author Li
     * @date 2022/11/23 09:16
     */
    @Override
    public boolean deleteCourse(Long id) {
        LambdaQueryWrapper<Course> wrapper = new LambdaQueryWrapper();
        wrapper.eq(Course::getId, id);
        wrapper.eq(Course::getIsDeleted, 0);
        Course course = dao.selectOne(wrapper);
        if (ObjectUtil.isEmpty(course)) {
            throw new VcaException("该课程已被删除 ");
        }
        List<CourseScheduling> schedulings = courseSchedulingService.list(new LambdaQueryWrapper<CourseScheduling>().eq(CourseScheduling::getCourseId, course.getId()).eq(CourseScheduling::getIsDel, 0));
        if (ObjectUtil.isNotEmpty(schedulings)) {
            throw new VcaException("请先删除该课程的排期");
        }
        List<CourseAbout> abouts = courseAboutService.list(new LambdaQueryWrapper<CourseAbout>().eq(CourseAbout::getAboutMainId, id).eq(CourseAbout::getIsDeleted, 0));
        course.setIsDeleted(1);
        return transactionTemplate.execute(e -> {
            courseAboutService.delByids(abouts.stream().map(CourseAbout::getId).collect(Collectors.toList()));
            dao.update(course, new LambdaUpdateWrapper<Course>().eq(Course::getId, id).set(Course::getIsDeleted, 1));
            return Boolean.TRUE;
        });
    }
}
